<?php

namespace catchAdmin\stock\model;

use catchAdmin\stock\model\search\WarehouseConfigSearch;
use catchAdmin\storehouse\model\ProjectWarehouseConfig;
use catcher\base\CatchModel;
use catcher\CatchAuth;
use catcher\CatchResponse;
use think\Exception;
use think\facade\Cache;
use think\facade\Db;
use think\facade\Log;

/**
 *
 * @property int $id
 * @property string $config_id
 * @property string $name
 * @property int $pid
 * @property int $createtime
 * @property int $updatetime
 * @property int $sort
 * @property int $isstatus
 * @property int $level
 * @property int $deletetime
 */
class WarehouseConfig extends CatchModel
{
    use WarehouseConfigSearch;
    public $field = [
        // ID
        'id',
        // 编号
        'config_id',
        // 仓库名称
        'name',
        // 父id
        'parent_id',
        // 创建时间
        'created_at',
        // 更新时间
        'updated_at',
        // 排序
        'sort',
        // 数据状态
        'isstatus',
        // 层级
        'level',
        'creator_id',
        // 删除时间
        'deleted_at',
        'tenant_id' ,
        'serial_number',
        'usage',
        'address_description',
        'realation_name',
        'relation_phone',
        'max_load_weight',
        'max_load_length',
        'max_load_width',
        'max_load_height'
    ];
    
    public $name = 'db_warehouse_config';
    /**
    * 列表
   */
    public function getList($tenant_id = 0)
    {
        $where = [];
        if($tenant_id !== 0){
            $where[] = ['tenant_id','=',$tenant_id];
        }
        return $this->catchSearch()
                    ->order('sort', 'desc')
                    ->where($where)
                    ->select()
                    ->toTree();
    }
    public function getAtt($tenant_id = 0)
    {
        $where = [];
        $where[] = ['level','<=',2];
        if($tenant_id !== 0){
            $where[] = ['tenant_id','=',$tenant_id];
        }

        $model =  $this->catchSearch()
            ->order('sort', 'desc')
            ->where($where)
            ->select()
        ;

        foreach ($model as &$value){
            if(0 == $value['isstatus']){
                $value['disabled'] = "disabled";
            }
            //$value['_id_levels'] = (new WarehouseConfig)->where('config_id',$value['config_id'])->find()->full_id;
        }

        return $model->toTree();
           // ->toTree();
    }
    public function getSon($tenant_id = 0,$config_id='')
    {
        $parent_id = Db::table('db_warehouse_config')->where('config_id',$config_id)->value('id');
        $where = [];
        $where[] = ['parent_id','=',$parent_id];
        if($tenant_id !== 0){
            $where[] = ['tenant_id','=',$tenant_id];
        }

        $postParams = \request()->post();
        $search = $postParams['search'];
        $where[] = ['name','like',"%$search%"];

        $result =  $this->catchSearch()
            ->order('sort', 'desc')
            ->where($where)
            ->select();

        foreach ($result as &$value){
            if(0 == $value['isstatus']){
                $value['disabled'] = "disabled";
            }
        }

        return $result;
    }

    public function searchNameAttr($query, $value, $data)
    {
        $query->where('name','like', $value . '%');
    }

    /**
	 * 父类ID查找子分类
	**/
	public function get_all_child_cate($catid,$str = ''){
    	$child = $this->where('parent_id',$catid)->column('id');
    	if($child){
	        $str .= ",".implode(',',$child);
	        foreach($child as $key => $val){
	            $str = $this->get_all_child_cate($val,$str);
	        }
	    }
	    return trim($str,',');
	}

    // 插入或者修改前已经删除名字查询
    public static function onBeforeWrite($warehouse_config)
    {
        $model = $warehouse_config;
        $data = $model->toArray();

        $res = Db::table('db_warehouse_config')
            ->where('name',$data['name'])
            ->where('deleted_at','<>',0)
            ->find()
        ;

//        if($res){
//            throw new Exception('在已删除记录中找到该库名，请更换名称');
//        }
    }

    public static function onAfterInsert($warehouse_config){

        if(1 == $warehouse_config->level || $warehouse_config->level == ''){
            $warehouse_config->serial_number = "S" . str_pad($warehouse_config->id,5,'0',STR_PAD_LEFT);
        }elseif (2 == $warehouse_config->level || 3 == $warehouse_config->level){
            $warehouse_config->serial_number = "L" . str_pad($warehouse_config->id,8,'0',STR_PAD_LEFT);
        }

        $warehouse_config->save();
    }

    public function getTreeList($is_tree = true){

//        if(null != Cache::get('tray_list')){
//            return Cache::get('tray_list');
//        }
        $user = (new CatchAuth())->user();

        $where = [];
        $where[] =  ['deleted_at','=',0];
        $where[] = ['tenant_id','=',$user->tenant_id];
        $where[] = ['isstatus','=',1];

        $field = ['config_id','name','level','parent_id','id','address_description'];
        $warehouse_config =  Db::table('db_warehouse_config')
            ->field($field)->where($where)
            ->order('sort','desc')->select()->toArray();

//        array_walk($warehouse_config,function(&$value,$key){
//            $value['value'] = $value['id'];
//            $value['label'] = $value['name'];
//        });

        return $is_tree == true ?  $this->generateTree($warehouse_config) : $warehouse_config;
    }

    public function generateTree($data,$parent_id = 0)
    {
        $tree = [];
        $newData = array_combine(array_column($data,'id'),$data);

        foreach ($newData as $key => $datum) {
            $newData[$key]['value'] = $datum['id'];
            $newData[$key]['label'] = $datum['name'];
            if ($datum['parent_id'] == $parent_id) {
                //根节点直接把地址放到新数组中
                $tree[] = &$newData[$key];
            } else {
                //不是根节点的将自己的地址放到父级的child节点
                $newData[$datum['parent_id']]['children'][] = &$newData[$key];
                //$newData[$datum['parent_id']]['son'][] = &$newData[$key];
            }
        }
        return $tree;
    }

    public function digui($array, $parent_id=0){

        $list = [];
        foreach ($array as &$value) {
            if ($value['parent_id'] == $parent_id) {
                if(!empty($lst =  $this->digui($array, $value['id']))){
                    $value['children'] = $lst;
                    $value['son'] = $lst;
                }

                $list[] = $value;
            }
        }
        return $list;
    }

    public function typesetting($array){

        $arr = [];
        if(!empty($array)){
            foreach ($array as $value){
                if(empty($value['children'])){
                    continue;
                    throw new Exception('检查是否存在空库区');
                }
                foreach ($value['children'] as $v){
                    if(empty($v['children'])){
                        continue;
//                        throw new Exception('检查库区是否存在空库位');
                    }
                    foreach ($v['children'] as &$v1){
                        $v1['config_level_1'] = $value['id'];
                        $v1['config_level_2'] = $v['id'];
                        $v1['config_level_3'] = $v1['id'];
                        $arr[] = $v1;
                    }
                }
            }
        }

        return $arr;
    }

    public function available($project_id=''){
        $project = new ProjectWarehouseConfig;

        $p1 = [];
        if(!empty($project_id)){
            $project =  $project->where('project_id','<>',$project_id);

        }

        $project = $project->select()->toArray();

        $warehouse_config_list = $this->getTreeList();

        //return $warehouse_config_list;

        $notEmptyArr = [];
        if(!empty($project_id)){

            $project_config_ids = [];

            //取出别人家的项目苦味-2级 3级组合
            $other = Db::table('db_project_warehouse_config')
                ->where([
                    ['deleted_at','=',0],
                    ['project_id','<>',$project_id]
                ])->select()->toArray();


            $config_level_2_ids = [];
            foreach ($other as $value){
                if(0 != $value['config_level_3']){
                    $project_config_ids[] = $value['config_level_3'];
                }else{//说明是二级全部的，收集起来
                    $project_config_ids[] = $value['config_level_2'];
                    $config_level_2_ids[] = $value['config_level_2'];
                }
            }

            //开始处理获取所有分区全部库位
            if(!empty($config_level_2_ids)){
                $config_level_3_result = Db::table('db_warehouse_config')
                    ->field('id')
                    ->where([
                        ['deleted_at','=',0],
                        ['level','=',3],
                        ['isstatus','=',1],
                        ['parent_id','in',$config_level_2_ids]
                    ])->select()->toArray();

                //dd($config_level_3_result);
                $config_level_3_ids =  array_column($config_level_3_result,'id');
            }

            //合并库位数组
            $notEmptyArr =  !empty($config_level_2_ids) ? array_merge($project_config_ids,$config_level_3_ids) : $project_config_ids;

        }

        //dd($notEmptyArr);

        //过滤空库名
        foreach ($warehouse_config_list as &$v){
            if(empty($v['children'])){
                $v['disabled'] = 'disabled';
                continue;
            }
            foreach ($v['children'] as &$v_v_2){
                if(empty($v_v_2['children'])){
                    $v_v_2['disabled'] = 'disabled';
                    continue;
                }
            }
        }

        foreach ($project as $value){
            if(0 == $value['config_level_3']){//代表是全选了2级库位，全部删除
                foreach ($warehouse_config_list as $w_key =>  &$w_value){
                        if(empty($w_value['children'])){
                            $value['disabled'] = 'disabled';
                            continue;
                        }
                        foreach ($w_value['children'] as $w_key_1 => &$w_value_1){
                            if($w_value_1['id'] == $value['config_level_2']){

                                if(empty($project_id)){
                                    $w_value_1['disabled'] ='disabled';
                                }else{
                                    if(!empty($notEmptyArr) && in_array($value['config_level_2'],$notEmptyArr)){
                                        $w_value_1['disabled'] ='disabled';
                                    }
                                }


//                                //判断是否自己选中
//                                if(!empty($check_ids) && in_array($value['config_level_2'],$check_ids)){
//                                    $w_value_1['checked'] ='checked';
//                                }


                                //array_splice($warehouse_config_list[$w_key]['children'],$w_key_1,1);
//                                unset($warehouse_config_list[$w_key]['children'][$w_key_1]);
                            }
                        }

                }

            }else{
                foreach ($warehouse_config_list as $w_key =>  &$w_value){
                    if(empty($w_value['children'])){
                        $value['disabled'] = 'disabled';
                        continue;
                    }
                    foreach ($w_value['children'] as $w_key_1 => &$w_value_1){

                        if(empty($w_value_1['children'])){
                            $w_value_1['disabled'] = 'disabled';
                            continue;
                        }

                        foreach ($w_value_1['children'] as $w_key_2 => &$w_value_2){
                            if($w_value_2['id'] == $value['config_level_3']){

                                if(empty($project_id)){
                                    $w_value_2['disabled'] ='disabled';
                                }else{
                                    if(!empty($notEmptyArr) && in_array($value['config_level_3'],$notEmptyArr)){
                                        $w_value_2['disabled'] ='disabled';
                                    }
                                }

//                                if(!empty($check_ids) && in_array($value['config_level_3'],$check_ids)){
//                                    $w_value_2['checked'] ='checked';
//                                }
                                //array_splice($warehouse_config_list[$w_key]['children'][$w_key_1]['children'],$w_key_2,1);
//                                unset($warehouse_config_list[$w_key]['children'][$w_key_1]);
                            }
                        }


                    }

                }
            }

        }

//        return $warehouse_config_list;

        return array_values($warehouse_config_list);
    }

    public function getProjectCheckList($project_id){

        $arr = [];
        //取出项目苦味-2级 3级组合
        $other = Db::table('db_project_warehouse_config')
            ->where([
                ['deleted_at','=',0],
                ['project_id','=',$project_id],
            ])->select()->toArray();


        foreach ($other as $value){
            if(0 != $value['config_level_3']){
                $arr[] = [$value['config_level_1'],$value['config_level_2'],$value['config_level_3']];
            }else{//
                //取出所有分区下面的库位
                $config_level3_result = Db::table('db_warehouse_config')
                    ->field('id')
                    ->where([
                        ['deleted_at','=',0],
                        ['level','=',3],
                        ['isstatus','=',1],
                        ['parent_id','=',$value['config_level_2']]
                    ])->select()->toArray();
                if(!empty($config_level3_result)){
                    $res_ids = array_column($config_level3_result,'id');
                    foreach ($res_ids as $v){
                        $arr[] = [$value['config_level_1'],$value['config_level_2'],$v];
                    }
                }

            }
        }

        return $arr;

    }

    public function getProjectLevel3Status($project_id){

        $arr = [];
        //取出项目苦味-2级 3级组合
        $other = Db::table('db_project_warehouse_config')
            ->where([
                ['deleted_at','=',0],
                ['project_id','=',$project_id]
            ])->select()->toArray();


        foreach ($other as $value){
            if(0 != $value['config_level_3']){
                if(0 == Db::table('db_warehouse_config')->where('id',$value['config_level_3'])->value('isstatus')){
                    continue;
                }
                $arr[$value['config_level_3']]['pos'] = [$value['config_level_1'],$value['config_level_2'],$value['config_level_3']];
            }else{//
                //取出所有分区下面的库位
                $config_level3_result = Db::table('db_warehouse_config')
                    ->field('id')
                    ->where([
                        ['deleted_at','=',0],
                        ['level','=',3],
                        ['isstatus','=',1],
                        ['parent_id','=',$value['config_level_2']]
                    ])->select()->toArray();
                if(!empty($config_level3_result)){
                    $res_ids = array_column($config_level3_result,'id');
                    foreach ($res_ids as $v){
                        $arr[$v]['pos'] = [$value['config_level_1'],$value['config_level_2'],$v];
                    }
                }

            }
        }



        //$level3_ids = array_column($arr,2);

        $level3_ids = array_keys($arr);

//        return $arr ;

        //拿到上面所有库位信息
        $level3_ids_result = $this->where('id','in',$level3_ids)->select()->toArray();

        foreach ($level3_ids_result as $value){
            $arr[$value['id']]['res'] = $value;
        }

        //return $level3_ids;
//        return array_values($arr);
        $arr = array_values($arr);

        $usage_1 = $usage_2 = $usage_3 = [];

//        dd($arr);

        foreach ($arr as &$value){
            $value['res']['pos'] = $value['pos'];
            if(null == $value['res']['usage'] || 1 == $value['res']['usage']){//存储
                $usage_1[] = $value['res'];
            }elseif ( 2 == $value['res']['usage']){
                $usage_2[] = $value['res'];
            }elseif (3 == $value['res']['usage']){
                $usage_3[] = $value['res'];
            }
        }

//        var_dump($arr);die();

//        var_dump([
//            'usage_1'=>$usage_1,
//            'usage_2'=>$usage_2,
//            'usage_3'=>$usage_3,
//        ]);die();


        return [
            'usage_1'=>$usage_1,
            'usage_2'=>$usage_2,
            'usage_3'=>$usage_3,
        ];
    }

    public function getProjectLevel2Tree($list){
        if(empty($list['usage_1']) && empty($list['usage_2']) && empty($list['usage_3'])){
            throw new Exception('没有分配储存、隔离、暂放任一库位');
        }

        $return = [

        ];

        foreach ($list as $key1 => $value1){
            if(empty($value1)){
                $return[$key1] = [];
                continue;
            }

            $usage_pos =  array_column($value1,'pos');

            $usage_pos_arr = [];
            foreach ($usage_pos as $value2){
                $usage_pos_arr[] = [$value2[0],$value2[1]];
            }
            $usage_pos_arr = $this->array_unique_fb($usage_pos_arr);

            $usage_tree_arr = [];
            foreach ($usage_pos_arr as $value){
                if(array_key_exists($value[0],$usage_tree_arr)){
                    $usage_tree_arr[$value[0]]['children'][] = $value[1];
                }else{
                    $usage_tree_arr[$value[0]] = [
                        'tree_id'=>$value[0],
                        'children'=>[$value[1]]
                    ];
                }
            }
            $usage_tree_arr = array_values($usage_tree_arr);

            foreach ($usage_tree_arr as &$value_usage){
                //var_dump($key_usage);die();
                //父ID替换成父数据
                $parent_id = $value_usage['tree_id'];
                $children_id = $value_usage['children'];
                unset($value_usage['tree_id']);
                $value_usage = Db::table('db_warehouse_config')->where('id',$parent_id)->find();
//                //赠送给前端的字段，方便数据展示
//                $value_usage['label'] = $value_usage['name'];
//                $value_usage['value'] = $value_usage['id'];

                //分区替换成分区数组
                $value_usage['children'] = Db::table('db_warehouse_config')
                    ->where('id','in',$children_id)
                    ->select()->toArray();
//                //赠送给前端的字段，方便数据展示
//                foreach ($value_usage['children'] as &$vvvv){
//                    $vvvv['label'] = $vvvv['name'];
//                    $vvvv['value'] = $vvvv['id'];
//                }

                //没有意义-算了不计算了
//                $value_usage['children_count'] = count($value_usage['children']);
            }

            $return[$key1] = $usage_tree_arr;
        }

        return $return;
    }

    //二维数组去重
    public function array_unique_fb($array2D=[]) {
        $temp = [];
        foreach ($array2D as $v) {
            $v = join(",", $v); //降维,也可以用implode,将一维数组转换为用逗号连接的字符串
            $temp[] = $v;
        }
        $temp = array_unique($temp);//去掉重复的字符串,也就是重复的一维数组
        foreach ($temp as $k => $v) {
            $temp[$k] = explode(",", $v);//再将拆开的数组重新组装
        }
        return $temp;
    }


    public function checkConfig($needle,$haystack){

        $temp = [];
        foreach ($haystack as $value){
            $one = $value['config_level_1'];
            $two = $value['config_level_2'];
            $three = $value['config_level_3'];

            $temp[$one][$two][$three] = $three;
        }

        $tempArr = [];

        $arr1 = $needle;

        foreach ($arr1 as $value){
            $one = $value[0];
            $two = $value[1];
            $three = $value[2];

            unset($temp[$one][$two][$three]);
            $tempArr[$one][$two][]  =  $three;
            if(empty($temp[$one][$two])){
                unset($temp[$one][$two]);
                $tempArr[$one][$two] = [];
            }

        }

        $l = [];
        foreach ($tempArr as $key => $value){
            foreach ($value as $k1 => $v1){
                if(!empty($v1)){
                    foreach ($v1 as $k2 => $v2){
                        $l[] = $key . ',' . $k1 . ',' . $v2;
                    }
                }else{
                    $l[] = $key . ',' . $k1 . ',0';
                }
            }
        }

        return $l;
    }

    public function  getProjectWarehouseConfigListByPid($project_id){
        $project_warehouse_config = Db::table('db_project_warehouse_config')
            ->where([
                ['project_id','=',$project_id],
                ['deleted_at','=',0]
            ])->select()->toArray()
        ;

        $project_level_1_ids = array_column($project_warehouse_config,'config_level_1');
        $project_level_2_ids = array_column($project_warehouse_config,'config_level_2');
        $project_level_3_ids = [];

        foreach ($project_warehouse_config as $value){
            if(0 != $value['config_level_3']){
                $project_level_3_ids[] =  $value['config_level_3'];
            }else{//
                //取出所有分区下面的库位
                $config_level3_result = Db::table('db_warehouse_config')
                    ->field('id')
                    ->where([
                        ['deleted_at','=',0],
                        ['level','=',3],
                        ['isstatus','=',1],
                        ['parent_id','=',$value['config_level_2']]
                    ])->select()->toArray();
                if(!empty($config_level3_result)){
                    $config_level3_ids  = array_column($config_level3_result,'id');
                    $project_level_3_ids = array_merge($project_level_3_ids,$config_level3_ids);
                }

            }
        }


        $project_level_all_ids = array_values(array_unique(array_merge($project_level_1_ids,$project_level_2_ids,$project_level_3_ids)));

        $return_list = Db::table('db_warehouse_config')->where('id','in',$project_level_all_ids)->select()->toArray();

        return $return_list;
    }

    //空库存库位
    public function getEmptyConfig($config_level3_ids = []){
        $where = [];
        $where[] = ['id','in',$config_level3_ids];

        $data= $this
            ->field("*")
            ->where($where)
            ->select()
            ->toArray();

        foreach ($data as $key => $value){
            //1。库存 0 未出库 2 部分出库 都是不满足的
            $map=[];
            $map[]=['deleted_at','=',0];
            $map[]=['status','in',[0,2]];
            $map[]=['config_id','=',$value['config_id']];
            $arr=Db::table('db_stock')->field('id')->where($map)->find();
            if(!empty($arr)){//不满足，不好意思
                unset($data[$key]);
                continue;
            }

            //2。并且托盘表不能有未入库的记录
            $map=[];
            $map[]=['deleted_at','=',0];
            $map[]=['status','=',0];
            $map[]=['config_id','=',$value['config_id']];
            $arr=Db::table('db_tray')->field('id')->where($map)->find();
            if(!empty($arr)){
                unset($data[$key]);
            }
        }

        return array_values($data);
    }

    //有库存库位
    public function getNotEmptyConfig($config_level3_ids = []){
        $where = [];
        $where[] = ['id','in',$config_level3_ids];

        $data= $this
            ->field("*")
            ->where($where)
            ->select()
            ->toArray();

        $temp = [];
        foreach ($data as $key => $value){
            $map=[];
            $map[]=['deleted_at','=',0];
            $map[]=['status','in',[0,2]];
            $map[]=['config_id','=',$value['config_id']];
            $arr=Db::table('db_stock')->field('id')->where($map)->find();
            if(!empty($arr)){
                $temp[] = $value;
            }
        }

        return $temp;
    }

    //三级库位查找 库名（一级） 库区（二级）
    public function getOneTwoLevelByThreeId($config_id){

        $warehouse_config_level3 = Db::table('db_warehouse_config')
            ->field('id,parent_id')
            ->where('config_id',$config_id)
            ->where('level',3)
            ->find();

        if(!$warehouse_config_level3){
            return false;
        }

        $warehouse_config_level2 = Db::table('db_warehouse_config')->where('id',$warehouse_config_level3['parent_id'])->find();
        $warehouse_config_level1 = Db::table('db_warehouse_config')->field('config_id,name')->where('id',$warehouse_config_level2['parent_id'])->find();

        return [
            'level_1_config_id'=>$warehouse_config_level1['config_id'],
            'level_2_config_id'=>$warehouse_config_level2['config_id'],
            'level_3_config_id'=>$config_id
        ];
    }

    //库位使用率
    public function rate(){
        $user = (new CatchAuth)->user();

        $stockModel = new Stock;
        $where = [
            ['deleted_at','=',0],
            ['status','<>','1']
        ];

        if($user['type'] !== 1) {//普通商户
            $where[] = ['tenant_id','=',$user['tenant_id']];
        }

        //使用的库位
        $stockWarehouseConfig = $stockModel->where($where)->column('config_id');

        $where[] = ['isstatus','=',1];
        $where[] = ['level','=',3];

        foreach ($where as $key => &$value){
            if('status' == $value[0]){
                unset($where[$key]);
                break;
            }
        }

        $warehouseConfig = Db::table('db_warehouse_config')->where($where)->count();

        return $warehouseConfig == 0 ? '-' : number_format(count(array_unique($stockWarehouseConfig)) / $warehouseConfig,2) * 100 . "%";
    }

    public function parentCategory()
    {
        return $this->belongsTo(WarehouseConfig::class, 'parent_id');
    }

    //获取库位全名
    public function getFullNameAttr()
    {
        $fullName = $this->getData('name');
        $parent = $this->parentCategory;
        while ($parent) {
            $fullName = $parent->getData('name') . ' > ' . $fullName;
            $parent = $parent->parentCategory;
        }
        return $fullName;
    }

    public function getFullIdAttr()
    {
        $fullName = $this->getData('id');
        $parent = $this->parentCategory;
        while ($parent) {
            $fullName = $parent->getData('id') . ',' . $fullName;
            $parent = $parent->parentCategory;
        }
        return $fullName;
    }
}